上一篇已經完成了 JWT 的部分功能
接著開始完善 JWT 功能
完成後的資料夾結構如下
schema.resolvers.go 實現 CreateUser funciotn
func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser) (string, error) {
	var user users.User
	user.Username = input.Username
	user.Password = input.Password
	user.Create()
	token, err := jwt.GenerateToken(user.Username)
	if err != nil{
		return "", err
	}
	return token, nil
}
$ go run server.go 測試一下 CreateUser 能不能成功
打開 http://localhost:8080/ 輸入
mutation {
  createUser(input: {username: "user1", password: "123"})
}
接著會得到一串 JWT string
{
  "data": {
    "createUser": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2ODM2MjU1ODcsInVzZXJuYW1lIjoidXNlcjEifQ.FUO8LH8G_FioVmVVMqVhQiqEndmbK_QIdq5KlHFWtwY"
  }
}
這階段開始實作當輸入了正確的帳號密碼,就會產生 JWT Token 給 userinternal/users/users.go 實作 Authenticate function
不過要注意一下...這段 Query 是練習做實驗才用的,不然這樣是有暴露密碼的危險性
func (user *User) Authenticate() bool {
	statement, err := mig.Db.Prepare("select Password from Users WHERE Username = ?")
	if err != nil {
		log.Fatal(err)
	}
	row := statement.QueryRow(user.Username)
	var hashedPassword string
	err = row.Scan(&hashedPassword)
	if err != nil {
		if err == sql.ErrNoRows {
			return false
		} else {
			log.Fatal(err)
		}
	}
	return CheckPasswordHash(user.Password, hashedPassword)
}
schema.resolvers.go 實作 Login function
func (r *mutationResolver) Login(ctx context.Context, input model.Login) (string, error) {
	var user users.User
	user.Username = input.Username
	user.Password = input.Password
	correct := user.Authenticate()
	if !correct {
		// 1
		return "", &users.WrongUsernameOrPasswordError{}
	}
	token, err := jwt.GenerateToken(user.Username)
	if err != nil{
		return "", err
	}
	return token, nil
}
internal/users/errors.go 處理錯誤回傳
package users
type WrongUsernameOrPasswordError struct{}
func (m *WrongUsernameOrPasswordError) Error() string {
	return "wrong username or password"
}
schema.resolvers.go 處理 Refresh Token
func (r *mutationResolver) RefreshToken(ctx context.Context, input model.RefreshTokenInput) (string, error) {
	username, err := jwt.ParseToken(input.Token)
	if err != nil {
		return "", fmt.Errorf("access denied")
	}
	token, err := jwt.GenerateToken(username)
	if err != nil {
		return "", err
	}
	return token, nil
}